/*
 *  util.cpp
 */

#include <arpa/inet.h>
#include <cstdlib>
#include <cstring>
#include <ctype.h>
#include <sstream>
#include <netdb.h>
#include <string>
#include <sys/socket.h>
#include <vector>

#include "util.h"

int Util::getline(char** buff, int size)
{
    int i;
    char c;
    for (i = 0; i < size - 1 && (c = getchar()) != '\n' && c != EOF ; ++i) {
        if (i == (size - 2))
            *buff = (char*) realloc(*buff, (size += size/2));
        *(*buff + i) = c;
    }
    *(*buff + i) = '\0';
    return i;
}

int Util::fgetline(FILE *fp, char** buff, int size)
{
    int i;
    char c;
    for (i = 0; i < size - 1 && (c = fgetc(fp)) != '\n' && c != EOF ; ++i) {
        if (i == (size - 2))
            *buff = (char*) realloc(*buff, (size += size/2));
        *(*buff + i) = c;
    }
    *(*buff + i) = '\0';
    return i;
}

void Util::trim(char *s)
{
    int len = strlen(s);
    for (int i = len - 1; i >= 0; --i) {
        if (s[i] == ' ' || s[i] == '\t') s[i] = '\0';
        else
            break;
    }

    int d;    //displacement
    for (d = 0; d < len; ++d) {
        if (s[d] != ' ' && s[d] != '\t') break;
    }
    
    int i;
    for (i = 0; i < len-d; ++i) {
        s[i] = s[i+d];
    }
    s[i] = '\0';
}

int Util::isnum(const char *str)
{
    if (strlen(str) == 0) return 0;
    for (int i = 0; i < strlen(str); ++i)
        if (!isdigit(str[i])) return 0;
    return 1;
}

int Util::isalphanum(const char *str)
{
    int retval = 1;
    for (int i = 0; i < strlen(str) && retval; ++i)
        retval = isalnum(*(str + i));
    return retval;
}

int Util::isipaddr(const char *str)
{
    struct sockaddr_in sa;
    return inet_pton(AF_INET, str, &(sa.sin_addr)) != 0;
}

int Util::stoi(const std::string s)
{
    if (!isnum(s.c_str())) {
        std::invalid_argument e("Not a number");
        throw e;
    }
    std::istringstream iss(s);
    int i;
    iss >> i; 
    return i;
}

std::string Util::itos(const int i)
{
    std::stringstream out;
    out << i;
    return out.str();
}

std::vector<std::string>* Util::split(std::string& str,
                                      const std::string& separator) {
    size_t start = 0;
    size_t end = 0;
    std::vector<std::string> *v = new std::vector<std::string>();
    std::string s;
    while (end != std::string::npos) {
        end = str.find(separator, start);
        s = str.substr(start, (end == std::string::npos)
                                  ? std::string::npos
                                  :end-start);
        v->push_back(s);

        // If at end, use start=maxSize.  Else use start=end+delimiter.
        start = (end > (std::string::npos-separator.size()))
                    ? std::string::npos
                    : end + separator.size();
    }
    return v;
}

//{+}

